package Utils.db;

import Utils.reflect.ReflectUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * ApacheDbUtils工具类
 *
 * @author d11yu
 */
public class ApacheDbUtilsUtils {
    private static final QueryRunner runner = new QueryRunner();

    /**
     * 通用增删改操作
     *
     * @param conn   数据库连接
     * @param sql    SQL语句
     * @param params 填入SQL语句的参数
     * @return 返回受影响的行数，如果返回值为-1，则说明执行失败。
     */
    public static int update(Connection conn, String sql, Object... params) {
        try {
            return runner.update(conn, sql, params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * 批量修改数据库
     *
     * @param conn       数据库连接
     * @param sql        sql语句
     * @param params     传入参数列表
     * @param fieldNames 要获取的字段名称
     * @return
     */
    public static <T> int[] updateBatch(Connection conn, String sql, List<T> params, String[] fieldNames) throws NoSuchFieldException, IllegalAccessException {
        return updateBatch(conn, sql, params, fieldNames, true);
    }

    /**
     * 批量修改数据库
     *
     * @param conn       数据库连接
     * @param sql        sql语句
     * @param params     传入参数列表
     * @param fieldNames 要获取的字段名称
     * @param isCommit   是否commit，默认为true
     * @return
     * @param <T>
     */
    public static <T> int[] updateBatch(Connection conn, String sql, List<T> params, String[] fieldNames, boolean isCommit) throws NoSuchFieldException, IllegalAccessException {
        Object[][] paramsNew = new Object[params.size()][fieldNames.length];
        for (int i = 0; i < params.size(); i++) {
            Object[] values = ReflectUtils.getDeclaredFieldValues(params.get(i), fieldNames);
            for (int j = 0; j < values.length; j++) {
                paramsNew[i][j] = values[j];
            }
        }
        return updateBatch(conn, sql, paramsNew, isCommit);
    }

    /**
     * 批量修改数据库
     *
     * @param conn   数据库连接
     * @param sql    sql语句
     * @param params 传入的二维数组
     * @param isCommit 是否commit
     * @return
     */
    public static int[] updateBatch(Connection conn, String sql, Object[][] params, boolean isCommit) {
        try {
            boolean isAutoCommit = conn.getAutoCommit();
            if (isAutoCommit) {
                conn.setAutoCommit(false);
            }
            int[] res = runner.batch(conn, sql, params);
            if (isCommit) {
                conn.commit();
            }
            if (isAutoCommit) {
                conn.setAutoCommit(isAutoCommit);
            }
            return res;
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                conn.rollback();
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
        }
        return null;
    }

    /**
     * 查询操作，仅返回一条记录（返回Java Bean），如果返回null，则说明执行失败。
     *
     * @param clazz  返回记录的Java Bean对象类
     * @param conn   数据库连接
     * @param sql    SQL语句
     * @param params SQL语句中的插入参数
     * @param <T>
     * @return
     */
    public static <T> T queryBean(Class<T> clazz, Connection conn, String sql, Object... params) throws SQLException {
            BeanHandler<T> handler = new BeanHandler<>(clazz);
            return runner.query(conn, sql, handler, params);
    }

    /**
     * 查询操作，以Java Bean List的形式返回多条记录，如果返回null，则说明执行失败。
     *
     * @param clazz  返回记录的Java Bean对象类
     * @param conn   数据库连接
     * @param sql    SQL语句
     * @param params SQL语句中的插入参数
     * @param <T>
     * @return
     */
    public static <T> List<T> queryBeanList(Class<T> clazz, Connection conn, String sql, Object... params) throws SQLException {
            BeanListHandler<T> handler = new BeanListHandler<>(clazz);
            return runner.query(conn, sql, handler, params);
    }

    /**
     * 查询操作，仅返回一条记录（返回Map<String,Object>），如果返回null，则说明执行失败。
     *
     * @param conn   数据库连接
     * @param sql    SQL语句
     * @param params SQL语句中的插入参数
     * @return
     */
    public static Map<String, Object> queryMap(Connection conn, String sql, Object... params) throws SQLException {
            MapHandler handler = new MapHandler();
            return runner.query(conn, sql, handler, params);
    }

    /**
     * 查询操作，以Java Bean List的形式返回多条记录，如果返回null，则说明执行失败。
     *
     * @param conn   数据库连接
     * @param sql    SQL语句
     * @param params SQL语句中的插入参数
     * @return
     */
    public static List<Map<String, Object>> queryMapList(Connection conn, String sql, Object... params) throws SQLException {
        MapListHandler handler = new MapListHandler();
        return runner.query(conn, sql, handler, params);
    }

    /**
     * 查询特殊值，如果返回null，则说明执行失败，如果返回null，则说明执行失败。
     *
     * @param conn   数据库连接
     * @param sql    SQL语句
     * @param params SQL语句中的插入参数
     * @return
     */
    public static Object queryScalar(Connection conn, String sql, Object... params) throws SQLException {
        ScalarHandler handler = new ScalarHandler();
        return runner.query(conn, sql, handler, params);
    }
}
